#include<func.h>
typedef struct Client_s
{
    int netfd;
    int isAlive; //判断是否存活 

}Client_t;
int main(int argc,char*argv[])
{
    // ./server_liaotian 192.168.213.128 1234
    ARGS_CHECK(argc,3);
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    //bind
    struct sockaddr_in addr;
    addr.sin_family =AF_INET;
    addr.sin_port = htons(atoi(argv[2]));
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    int flag = 1;
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag));
    int ret = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)); // ret 返回值是检查是否正确
    ERROR_CHECK(ret,-1,"bind");
    //listen
    listen(sockfd,10);
    //connect
    //先select 后connect
    fd_set rdset;//就绪序列
    fd_set mdset;//监听序列
    //先把sockfd 放在监听集合
    FD_SET(sockfd,&mdset);
    //设置client集合
    Client_t Client[1024]; 
    int clinentNum;//统计连接的客户端个数
    char buf[4096]={0};
    //开始连接
    while(1)
    {
        //把监听集合拷贝到就绪集合
        memcpy(&rdset,&mdset,sizeof(fd_set));//拷贝
        //aaaaa 我直到错在哪儿了！
        select(1024,&rdset,NULL,NULL,NULL);//监听是否有人连接进入半连接状态
        //如果sockfd有消息
        //这里完成了有连接加入
        if(FD_ISSET(sockfd,&rdset))
        {
            //有netfd 
            printf("net is coming!\n");
            int netfd = accept(sockfd,NULL,NULL);
            //打印一下是谁连接上了把
            
            //记录新的客户端
            Client[clinentNum].netfd = netfd;
            Client[clinentNum].isAlive = 1;
            //添加到就绪队列
            FD_SET(Client[clinentNum].netfd,&mdset);
            clinentNum++;
        }
        for(int i = 0;i<clinentNum;i++)
        {
            //连接到客户端
            if(Client[i].netfd != -1 && FD_ISSET(Client[i].netfd,&rdset))
            {
                printf("ready,netfd = %d\n",Client[i].netfd);
                //客户端就绪
                bzero(buf,sizeof(buf)); //..clear buf
                ssize_t sret = recv(Client[i].netfd,buf,sizeof(buf),0);
                ERROR_CHECK(sret,-1,"sret");
                //如果对方结束
                if(sret == 0)
                {
                    //将对方移出就绪队列，改变状态
                    Client[i].isAlive = 0;
                    FD_CLR(Client[i].netfd,&mdset);
                    //printf 谁退出了
                    printf("netfd = %d is out \n",Client[i].netfd);
                    close(Client[i].netfd);
                    continue;
                }
                for(int j=0; j < clinentNum;j++)
                {
                    if(j == i || Client[j].isAlive == 0)
                    {
                        continue;
                    }
                    send(Client[j].netfd,buf,strlen(buf),0);
                }
            }
        }
    }
    close(sockfd);
    return 0;

}